/**
`useMemo`  是 React 中的一个 Hook，用于优化性能，避免不必要的计算。它通过记忆（memoization）一个计算结果，只有在依赖项发生变化时才会重新计算。
  1. 基本概念
  - 记忆化计算： `useMemo`  允许你缓存一个计算结果，只有在依赖项发生变化时才会重新计算这个结果。
  - 性能优化：在性能敏感的组件中， `useMemo`  可以减少不必要的渲染和计算，提高应用的性能。

  2. 使用方式
  `useMemo`  接受两个参数：
  1. 一个创建函数，用于计算需要记忆的值。
  2. 一个依赖数组，只有在数组中的依赖项发生变化时，才会重新计算这个值。

   示例：
  jsx
  import React, { useMemo, useState } from 'react';

  const ExpensiveComponent = ({ items }) => {
    const [count, setCount] = useState(0);

    // 使用 useMemo 缓存计算结果
    const total = useMemo(() => {
      console.log('Calculating total...');
      return items.reduce((acc, item) => acc + item, 0);
    }, [items]); // 依赖于 items

    return (
      <div>
        <h1>Total: {total}</h1>
        <button onClick={() => setCount(count + 1)}>Increment Count</button>
        <p>Count: {count}</p>
      </div>
    );
  };
  3. 何时使用  `useMemo` 
  - 昂贵的计算：当计算结果的生成过程比较复杂或耗时时，使用  `useMemo`  可以避免在每次渲染时都进行计算。
  - 依赖项变化：只有当依赖项变化时，才需要重新计算值。通过合理设置依赖项，可以有效控制计算的时机。

  4. 注意事项
  - 不滥用： `useMemo`  主要用于性能优化，过度使用可能导致代码复杂性增加。在简单计算或小型组件中，通常不需要使用。
  - 依赖项管理：确保依赖数组中的所有依赖项都正确列出，以避免潜在的错误和不一致的状态。

  5. 总结
  `useMemo`  是 React 中用于性能优化的重要工具，可以帮助开发者缓存计算结果，避免不必要的计算和渲染。合理使用  `useMemo`  可以提高应用的性能，特别是在处理复杂计算和大型数据集时。理解其工作原理和使用场景，将有助于编写更高效的 React 组件。
 */
import React, { memo, useMemo, useState } from 'react'

const HelloWorld = memo(function(props) {
  console.log("HelloWorld被渲染~")
  return <h2>Hello World</h2>
})

function calcNumTotal(num) {
  // console.log("calcNumTotal的计算过程被调用~")
  let total = 0
  for (let i = 1; i <= num; i++) {
    total += i
  }
  return total
}

const App = memo(() => {
  const [count, setCount] = useState(0)

  // const result = calcNumTotal(50)

  // 1.不依赖任何的值, 进行计算
  // const result = useMemo(() => calcNumTotal(50), [])

  // 2.依赖count 
  const result = useMemo(() => calcNumTotal(count), [count])

  // 3.useMemo和useCallback的对比
  // const increment = useCallback(fn, [])
  // const increment2 = useMemo(() => fn, [])
  
  // 4.使用useMemo对子组件渲染进行优化
  const info = useMemo(() => ({name: "useMemo-name", age: 18}), [])
  
  return (
    <div>
      <h2>计算结果: {result}</h2>
      <h2>计数器: {count}</h2>
      <button onClick={e => setCount(count+1)}>+1</button>

      <HelloWorld result={result} info={info} />
    </div>
  )
})

export default App